package com.diyizu.youdianda.serviceImpl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.diyizu.youdianda.common.R;
import com.diyizu.youdianda.dto.SysMenuDto;
import com.diyizu.youdianda.dto.SysRoleDto;
import com.diyizu.youdianda.dto.SysRolePageDto;
import com.diyizu.youdianda.entity.SysMenu;
import com.diyizu.youdianda.entity.SysRole;
import com.diyizu.youdianda.entity.SysRoleMenu;
import com.diyizu.youdianda.mapper.SysRoleMapper;
import com.diyizu.youdianda.service.SysMenuService;
import com.diyizu.youdianda.service.SysRoleMenuService;
import com.diyizu.youdianda.service.SysRoleService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@Service
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements SysRoleService {

    @Autowired
    private SysRoleMenuService sysRoleMenuService;
    @Autowired
    private SysMenuService sysMenuService;

    //分页
    @Override
    public SysRolePageDto pageData(String name, Integer page, Integer limit) {
        //如果有角色名就拼接上
        LambdaQueryWrapper<SysRole> lqw = new LambdaQueryWrapper<>();
        lqw.like(StringUtils.isNotEmpty(name), SysRole::getName, name);
        //分页条件
        Page<SysRole> sysRolePage = new Page<>(page, limit);
        Page<SysRole> rolePage = this.page(sysRolePage, lqw);

        /*准备返回对象*/
        SysRolePageDto sysRolePageDto = new SysRolePageDto();
        //按照返回类型给予值
        sysRolePageDto.setCount((int) rolePage.getTotal()); //总记录数
        sysRolePageDto.setTotalPages((int) rolePage.getPages());  //总页数
        sysRolePageDto.setPageSize((int) rolePage.getSize());   //每页几条
        sysRolePageDto.setCurrentPage((int) rolePage.getCurrent()); //当前页

        //data里面只包含了单纯的sysRole对象，由于要和浏览器对应，使用SysRolePageDto
        List<SysRolePageDto> data = new ArrayList<>();
        //为sysRole中对应前端的字段赋值
        for (SysRole sysRole : rolePage.getRecords()) {
            //将分页数据对象的值赋给Dto
            SysRolePageDto sysRolePageDto1 = new SysRolePageDto();
            sysRolePageDto1.setId(sysRole.getId());
            sysRolePageDto1.setName(sysRole.getName());
            sysRolePageDto1.setDescription(sysRole.getDescription());
            sysRolePageDto1.setCreate_date(sysRole.getCreateDate());
            sysRolePageDto1.setUpdate_date(sysRole.getUpdateDate());
            sysRolePageDto1.setRemarks(sysRole.getRemarks());
            sysRolePageDto1.setDel_flag(sysRole.getDelFlag());
            sysRolePageDto1.setSuperadmin(sysRole.getSuperadmin());
            sysRolePageDto1.setDefault_data(sysRole.getDefaultData());

            //获取分页数据的ID
            String sysRoleId = sysRole.getId();
            //通过该ID查询它拥有哪些权限
            LambdaQueryWrapper<SysRoleMenu> sysRoleMenulqw = new LambdaQueryWrapper<>();
            sysRoleMenulqw.in(SysRoleMenu::getRoleId, sysRoleId);
            List<SysRoleMenu> list = sysRoleMenuService.list(sysRoleMenulqw);
            //分别赋值
            sysRolePageDto1.setRole_id(sysRoleId);
            //把当前角色对应的权限拿出来
            ArrayList<String> arrayList = new ArrayList<>();
            for (SysRoleMenu sysRoleMenu : list) {
                arrayList.add(sysRoleMenu.getMenuId());
            }
            sysRolePageDto1.setRole_menus(arrayList);   //赋予值

            //将封装好的sysRole对象放入新集合中
            data.add(sysRolePageDto1);
        }
        //最后将集合放入sysRolePageDto中
        sysRolePageDto.setData(data);

        return sysRolePageDto;
    }

    //添加
    @Override
    public void saveSysRole(SysRoleDto sysRoleDto) {
        SysRole sysRole = new SysRole();
        //复制数据，先除过权限数组
        BeanUtils.copyProperties(sysRoleDto, sysRole, "menuids");
        //添加角色表本身的数据
        this.save(sysRole);
        //添加完成后直接就能拿到对应的ID之
        String roleId = sysRole.getId();

        //添加权限表数据
        String[] menuids = sysRoleDto.getMenuids();
        for (String menuid : menuids) {
            SysRoleMenu sysRoleMenu = new SysRoleMenu();
            sysRoleMenu.setRoleId(roleId);
            sysRoleMenu.setMenuId(menuid);
            sysRoleMenuService.save(sysRoleMenu);
        }
    }

    //删除
    @Override
    public R<String> delSysRole(String id) {
        //如果是系统默认数据，不能删除
        String[] sysRoleIds = {"1c54e003c1fc4dcd9b087ef8d48abac3",
                "620003c0-e96c-11eb-845c-3d5efdbaf2d4", "6f64aa20-e96c-11eb-845c-3d5efdbaf2d4",
                "a78b5bd0-3c49-11ec-abdc-7ba81cf6c5ef", "be0e2540-3c49-11ec-abdc-7ba81cf6c5ef"};
        for (String sysRoleId : sysRoleIds) {
            if (sysRoleId.equals(id)){
                return R.error("系统默认数据，不允许删除", 1000);
            }
        }
        //不是默认数据才能删除
        this.removeById(id);
        return R.success("删除成功");
    }

    //角色详情(除了包含本表数据外，还需要权限数据)
    @Override
    public SysRole rowInfo(String id) {
        //本表数据
        LambdaQueryWrapper<SysRole> lqw = new LambdaQueryWrapper<>();
        lqw.eq(SysRole::getId, id);
        SysRole byId = this.getOne(lqw);

        /*权限数据(即菜单表)*/
        //通过roleId查询sys_role_menu里的menuId
        LambdaQueryWrapper<SysRoleMenu> sysRoleMenulqw = new LambdaQueryWrapper<>();
        sysRoleMenulqw.in(SysRoleMenu::getRoleId, id);
        List<SysRoleMenu> list = sysRoleMenuService.list(sysRoleMenulqw);

        //将查询到的权限数据放入集合中(一级列表)
        List<SysMenuDto> sysMenuDtoList = new ArrayList<>();
        //先判断它是否为一级权限
        LambdaQueryWrapper<SysMenu> lqw1 = new LambdaQueryWrapper<>();
        lqw1.like(SysMenu::getPath, "_");        //一级列表判断条件
        lqw1.notLike(SysMenu::getComponent, "/");//一级列表判断条件
        List<SysMenu> list1 = sysMenuService.list(lqw1);
        //通过menuId找到对应的数据
        for (SysRoleMenu sysRoleMenu : list) {
            //如果是就加进外部集合中
            for (SysMenu sysMenu : list1) {
                String s = sysMenu.getId().toString();
                //如果一级集合ID对应上sys_role_menu的menuId,那就加入集合
                if (s.equals(sysRoleMenu.getMenuId())){
                    SysMenuDto sysMenuDto = new SysMenuDto();
                    BeanUtils.copyProperties(sysMenu, sysMenuDto);
                    sysMenuDtoList.add(sysMenuDto);
                }
            }
        }

        //此时集合中数据是一级列表，将二级列表放入一级列表的children中
        for (SysMenuDto sysMenuDto : sysMenuDtoList) {
            Long sysMenuDtoId = sysMenuDto.getId();
            ArrayList<SysMenuDto> sysMenuDtos = new ArrayList<>();
            //查询有哪些二级列表
            for (SysRoleMenu sysRoleMenu : list) {
                String menuId = sysRoleMenu.getMenuId();
                SysMenu sysMenu = sysMenuService.getById(menuId);
                //二级列表的PID和一级列表的ID相同
                if (sysMenuDtoId.equals(sysMenu.getPid())){
                    //拷贝数据
                    SysMenuDto sysMenuDto1 = new SysMenuDto();
                    BeanUtils.copyProperties(sysMenu, sysMenuDto1);
                    //只要有相同的就把数据加进去
                    sysMenuDtos.add(sysMenuDto1);
                }
            }
            //把子项(二级列表)放进去
            sysMenuDto.setChildren(sysMenuDtos);
        }

        /*此时的集合内容对应二级列表，再次添加三级列表内容放进去*/
        //先拿到二级列表的ID
        ArrayList<Long> secondId = new ArrayList<>();
        for (SysMenuDto sysMenuDto : sysMenuDtoList) {
            for (SysMenuDto child : sysMenuDto.getChildren()) {
                secondId.add(child.getId());
            }
        }
        //先把三级列表数据放一个集合中
        ArrayList<SysMenuDto> sysMenus = new ArrayList<>();
        //再拿二级列表ID和对应的三级列表PID比较
        for (SysRoleMenu sysRoleMenu : list) {
            for (Long aLong : secondId) {
                //三级列表有很多，要以三级列表的menuId和二级列表的ID共同确定
                LambdaQueryWrapper<SysMenu> sysMenulqw = new LambdaQueryWrapper<>();
                sysMenulqw.eq(SysMenu::getId, sysRoleMenu.getMenuId());  //三级列表ID
                sysMenulqw.eq(SysMenu::getPid, aLong);  //三级列表PID(二级列表ID)
                SysMenu sysMenu = sysMenuService.getOne(sysMenulqw);
                //拷贝数据
                SysMenuDto sysMenuDto = new SysMenuDto();
                //不为空说明是正确的
                if (sysMenu != null){
                    BeanUtils.copyProperties(sysMenu, sysMenuDto);
                    sysMenus.add(sysMenuDto);
                }
            }
        }
        //再将该集合赋予二级列表的children
        for (SysMenuDto sysMenuDto : sysMenuDtoList) {
            for (SysMenuDto child : sysMenuDto.getChildren()) {
                child.setChildren(sysMenus);
            }
        }

        //最后封装权限表数据
        byId.setAuthList(sysMenuDtoList);
        return byId;
    }

    //修改
    @Override
    public void updateSysRole(SysRoleDto sysRoleDto) {
        SysRole sysRole = new SysRole();
        //拷贝角色表本身的数据，先除去menuids
        BeanUtils.copyProperties(sysRoleDto, sysRole, "menuids");
        //先修改sys_role表本身的数据
        this.updateById(sysRole);

        //再修改角色权限表sys_role_menu的数据
        //先删除(联合主键)
        String id = sysRole.getId();
        String[] menuids1 = sysRoleDto.getMenuids();

        LambdaQueryWrapper<SysRoleMenu> lqw = new LambdaQueryWrapper<>();
        lqw.eq(SysRoleMenu::getRoleId, id);
        //先找到用户角色的那些权限数据
        List<SysRoleMenu> list = sysRoleMenuService.list(lqw);
        //删除这个数据
        for (SysRoleMenu sysRoleMenu : list) {
            sysRoleMenuService.deleteByMultiId(sysRoleMenu);
        }

        //然后重新添加
        String[] menuids = sysRoleDto.getMenuids();
        for (String menuid : menuids) {
            //设置对象
            SysRoleMenu sysRoleMenu = new SysRoleMenu();
            sysRoleMenu.setRoleId(id);
            sysRoleMenu.setMenuId(menuid);
            //保存
            sysRoleMenuService.save(sysRoleMenu);
        }
    }
}
